/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 Huawei Technologies Co., Ltd */

#ifndef HINIC3_MBOX_H
#define HINIC3_MBOX_H

#include "hinic3_crm.h"
#include "hinic3_hwdev.h"

#define HINIC3_MBOX_PF_SEND_ERR			0x1 /* PF侧发送错误标志 */

#define HINIC3_MGMT_SRC_ID				0x1FFF /* 管理通道源功能号（用于DMA型消息判断） */
#define HINIC3_MAX_FUNCTIONS				4096  /* 最大功能数（PF+VF总数） */

/* 消息头定义（位段偏移/掩码） */
#define HINIC3_MSG_HEADER_SRC_GLB_FUNC_IDX_SHIFT	0   /* 源全局功能号偏移 */
#define HINIC3_MSG_HEADER_STATUS_SHIFT			13  /* 状态位偏移（1bit） */
#define HINIC3_MSG_HEADER_SOURCE_SHIFT			15  /* 来源（MGMT/MBOX）偏移 */
#define HINIC3_MSG_HEADER_AEQ_ID_SHIFT			16  /* 响应使用的AEQ编号偏移 */
#define HINIC3_MSG_HEADER_MSG_ID_SHIFT			18  /* 消息ID偏移 */
#define HINIC3_MSG_HEADER_CMD_SHIFT			22  /* 命令码偏移 */

#define HINIC3_MSG_HEADER_MSG_LEN_SHIFT			32 /* 长度偏移 */
#define HINIC3_MSG_HEADER_MODULE_SHIFT			43 /* 模块号偏移 */
#define HINIC3_MSG_HEADER_SEG_LEN_SHIFT			48 /* 分段长度偏移 */
#define HINIC3_MSG_HEADER_NO_ACK_SHIFT			54 /* 无需ACK偏移 */
#define HINIC3_MSG_HEADER_DATA_TYPE_SHIFT			55 /* 数据类型（内联/DMA）偏移 */
#define HINIC3_MSG_HEADER_SEQID_SHIFT			56 /* 序号偏移 */
#define HINIC3_MSG_HEADER_LAST_SHIFT				62 /* 最后一段偏移 */
#define HINIC3_MSG_HEADER_DIRECTION_SHIFT			63 /* 方向（请求/响应）偏移 */

#define HINIC3_MSG_HEADER_SRC_GLB_FUNC_IDX_MASK		0x1FFF /* 源功能号掩码 */
#define HINIC3_MSG_HEADER_STATUS_MASK			0x1    /* 状态掩码 */
#define HINIC3_MSG_HEADER_SOURCE_MASK			0x1    /* 来源掩码 */
#define HINIC3_MSG_HEADER_AEQ_ID_MASK			0x3    /* AEQ编号掩码 */
#define HINIC3_MSG_HEADER_MSG_ID_MASK			0xF    /* 消息ID掩码 */
#define HINIC3_MSG_HEADER_CMD_MASK			0x3FF  /* 命令码掩码 */

#define HINIC3_MSG_HEADER_MSG_LEN_MASK			0x7FF /* 长度掩码 */
#define HINIC3_MSG_HEADER_MODULE_MASK			0x1F  /* 模块掩码 */
#define HINIC3_MSG_HEADER_SEG_LEN_MASK			0x3F /* 分段长度掩码 */
#define HINIC3_MSG_HEADER_NO_ACK_MASK			0x1  /* 无需ACK掩码 */
#define HINIC3_MSG_HEADER_DATA_TYPE_MASK			0x1  /* 数据类型掩码 */
#define HINIC3_MSG_HEADER_SEQID_MASK			0x3F /* 序号掩码 */
#define HINIC3_MSG_HEADER_LAST_MASK				0x1  /* 最后一段掩码 */
#define HINIC3_MSG_HEADER_DIRECTION_MASK			0x1  /* 方向掩码 */

#define MBOX_MAX_BUF_SZ			2048U /* 单条MBOX消息最大字节数 */
#define MBOX_HEADER_SZ			8     /* 消息头长度 */
#define HINIC3_MBOX_DATA_SIZE		(MBOX_MAX_BUF_SZ - MBOX_HEADER_SZ) /* 最大数据长度 */

#define HINIC3_MSG_HEADER_GET(val, field)	\
		(((val) >> HINIC3_MSG_HEADER_##field##_SHIFT) & \
		 HINIC3_MSG_HEADER_##field##_MASK) /* 取字段值 */
#define HINIC3_MSG_HEADER_SET(val, field)	\
		((u64)(((u64)(val)) & HINIC3_MSG_HEADER_##field##_MASK) << \
		 HINIC3_MSG_HEADER_##field##_SHIFT) /* 构造字段值 */

#define IS_DMA_MBX_MSG(dst_func)	((dst_func) == HINIC3_MGMT_SRC_ID) /* 是否DMA型消息 */

enum hinic3_msg_direction_type {
	HINIC3_MSG_DIRECT_SEND	= 0, /* 请求方向 */
	HINIC3_MSG_RESPONSE	= 1,  /* 响应方向 */
};

enum hinic3_msg_segment_type {
	NOT_LAST_SEGMENT	= 0, /* 非最后一段 */
	LAST_SEGMENT		= 1, /* 最后一段 */
};

enum hinic3_msg_ack_type {
	HINIC3_MSG_ACK,   /* 需要ACK */
	HINIC3_MSG_NO_ACK,/* 不需要ACK */
};

enum hinic3_data_type {
	HINIC3_DATA_INLINE	= 0, /* 内联数据 */
	HINIC3_DATA_DMA		= 1, /* DMA数据 */
};

enum hinic3_msg_src_type {
	HINIC3_MSG_FROM_MGMT	= 0, /* 管理CPU */
	HINIC3_MSG_FROM_MBOX	= 1, /* 功能间MBOX */
};

enum hinic3_msg_aeq_type {
	HINIC3_ASYNC_MSG_AEQ	= 0, /* 异步消息AEQ */
	/* 指示目的功能或管理CPU用于响应MBOX消息的AEQ */
	HINIC3_MBOX_RSP_MSG_AEQ	= 1,
	/* 指示管理CPU用于响应API命令消息的AEQ */
	HINIC3_MGMT_RSP_MSG_AEQ	= 2,
};

#define HINIC3_MBOX_WQ_NAME	"hinic3_mbox" /* 工作队列名称 */

struct mbox_msg_info {
	u8 msg_id;  /* 消息ID */
	u8 status; /* 仅使用1 bit 表示状态 */
};

struct hinic3_msg_desc {
	void *msg;      /* 消息数据指针（内联或DMA缓冲） */
	u16 msg_len;    /* 消息长度 */
	u8 seq_id;      /* 分段序号 */
	u8 mod;         /* 模块号 */
	u16 cmd;        /* 命令码 */
	struct mbox_msg_info msg_info; /* 消息ID与状态 */
};

struct hinic3_msg_channel {
	struct hinic3_msg_desc	resp_msg; /* 响应消息缓存 */
	struct hinic3_msg_desc	recv_msg; /* 接收消息缓存 */

	atomic_t		recv_msg_cnt; /* 接收计数 */
};

/* Receive other functions mbox message */
struct hinic3_recv_mbox {
	void *msg;        /* 收到的消息体指针 */
	u16 msg_len;      /* 消息长度 */
	u8 msg_id;        /* 消息ID */
	u8 mod;           /* 模块号 */
	u16 cmd;          /* 命令码 */
	u16 src_func_idx; /* 源功能号 */

	enum hinic3_msg_ack_type ack_type; /* 是否需要ACK */
	u32 rsvd1;        /* 保留 */

	void *resp_buff;  /* 响应缓冲（由接收方填写） */
};

struct hinic3_send_mbox {
	u8 *data;      /* 待发送的数据指针 */

	u64 *wb_status; /* 写回状态地址 */
	void *wb_vaddr; /* 写回状态虚拟地址 */
	dma_addr_t wb_paddr; /* 写回状态物理地址 */
};

enum mbox_event_state {
	EVENT_START = 0,  /* 事件开始 */
	EVENT_FAIL,       /* 失败 */
	EVENT_SUCCESS,    /* 成功 */
	EVENT_TIMEOUT,    /* 超时 */
	EVENT_END,        /* 结束 */
};

enum hinic3_mbox_cb_state {
	HINIC3_VF_MBOX_CB_REG = 0,       /* VF侧回调注册完成 */
	HINIC3_VF_MBOX_CB_RUNNING,       /* VF侧回调执行中 */
	HINIC3_PF_MBOX_CB_REG,           /* PF侧回调注册完成 */
	HINIC3_PF_MBOX_CB_RUNNING,       /* PF侧回调执行中 */
	HINIC3_PPF_MBOX_CB_REG,          /* PPF侧回调注册完成 */
	HINIC3_PPF_MBOX_CB_RUNNING,      /* PPF侧回调执行中 */
	HINIC3_PPF_TO_PF_MBOX_CB_REG,    /* PPF->PF回调注册完成 */
	HINIC3_PPF_TO_PF_MBOX_CB_RUNNIG, /* PPF->PF回调执行中 */
};

enum hinic3_mbox_ack_type {
	MBOX_ACK,    /* 需要ACK */
	MBOX_NO_ACK, /* 不需要ACK */
};

struct mbox_dma_msg {
	u32		xor;            /* 校验/异或值 */
	u32		dma_addr_high;  /* DMA地址高32位 */
	u32		dma_addr_low;   /* DMA地址低32位 */
	u32		msg_len;        /* 消息长度 */
	u64		rsvd;           /* 保留 */
};

struct mbox_dma_queue {
	void *dma_buff_vaddr;    /* 队列DMA缓冲的虚拟地址 */
	dma_addr_t dma_buff_paddr; /* DMA缓冲物理地址 */

	u16 depth;    /* 深度（元素个数） */
	u16 prod_idx; /* 生产者索引 */
	u16 cons_idx; /* 消费者索引 */
};

struct hinic3_mbox {
	struct hinic3_hwdev *hwdev; /* 设备抽象指针 */

	bool			lock_channel_en; /* 是否启用通道级别锁 */
	unsigned long		channel_stop;   /* 通道停止位图 */
	u16			cur_msg_channel; /* 当前使用的消息通道 */
	u32			rsvd1;          /* 保留 */

	/* 保护发送消息与ACK收发的互斥锁 */
	struct mutex		mbox_send_lock;
	/* 仅保护发送消息（不含ACK）的互斥锁 */
	struct mutex		msg_send_lock;
	struct hinic3_send_mbox	send_mbox;   /* 发送上下文（写回区等） */

	struct mbox_dma_queue	sync_msg_queue;  /* 同步消息DMA队列 */
	struct mbox_dma_queue	async_msg_queue; /* 异步消息DMA队列 */

	struct workqueue_struct *workq; /* 工作队列（处理异步消息） */

	struct hinic3_msg_channel mgmt_msg; /* 驱动与管理CPU通道 */
	struct hinic3_msg_channel *host_msg; /* 主机间PPF消息通道（多宿主） */
	struct hinic3_msg_channel *func_msg; /* PF<->VF 功能间通道 */
	u16			num_func_msg; /* 功能通道个数 */
	bool			support_h2h_msg; /* 是否支持主机间消息 */

	/* VF接收PF/PPF的回调 */
	hinic3_vf_mbox_cb	vf_mbox_cb[HINIC3_MOD_MAX];
	void *vf_mbox_data[HINIC3_MOD_MAX];
	/* PF/PPF接收VF的回调 */
	hinic3_pf_mbox_cb	pf_mbox_cb[HINIC3_MOD_MAX];
	void *pf_mbox_data[HINIC3_MOD_MAX];
	/* PPF接收PF/PPF的回调 */
	hinic3_ppf_mbox_cb	ppf_mbox_cb[HINIC3_MOD_MAX];
	void *ppf_mbox_data[HINIC3_MOD_MAX];
	/* PF接收PPF的回调 */
	hinic3_pf_recv_from_ppf_mbox_cb	pf_recv_ppf_mbox_cb[HINIC3_MOD_MAX];
	void *pf_recv_ppf_mbox_data[HINIC3_MOD_MAX];
	unsigned long		ppf_to_pf_mbox_cb_state[HINIC3_MOD_MAX]; /* 回调状态位图 */
	unsigned long		ppf_mbox_cb_state[HINIC3_MOD_MAX];
	unsigned long		pf_mbox_cb_state[HINIC3_MOD_MAX];
	unsigned long		vf_mbox_cb_state[HINIC3_MOD_MAX];

	u8			send_msg_id; /* 当前发送的消息ID */
	u16			rsvd2;       /* 保留 */
	enum mbox_event_state	event_flag; /* 事件状态 */
	/* 保护事件标志的自旋锁（中断上下文可用） */
	spinlock_t		mbox_lock;
	u64			rsvd3;       /* 保留 */
};

struct hinic3_mbox_work {
	struct work_struct	work;       /* 工作项 */
	struct hinic3_mbox *func_to_func;/* 功能间MBOX上下文 */
	struct hinic3_recv_mbox *recv_mbox; /* 接收的MBOX消息 */
	struct hinic3_msg_channel *msg_ch;  /* 对应的消息通道 */
};

struct vf_cmd_check_handle {
	u16 cmd; /* 命令码 */
	bool (*check_cmd)(struct hinic3_hwdev *hwdev, u16 src_func_idx,
			  void *buf_in, u16 in_size); /* 校验VF命令合法性的回调 */
};

void hinic3_mbox_func_aeqe_handler(void *handle, u8 *header, u8 size); /* 功能侧AEQ事件处理（MBOX） */

bool hinic3_mbox_check_cmd_valid(struct hinic3_hwdev *hwdev,
				 struct vf_cmd_check_handle *cmd_handle,
				 u16 vf_id, u16 cmd, void *buf_in, u16 in_size,
				 u8 size); /* 校验VF发起的MBOX命令是否有效 */

int hinic3_func_to_func_init(struct hinic3_hwdev *hwdev); /* 初始化功能间MBOX通道 */

void hinic3_func_to_func_free(struct hinic3_hwdev *hwdev); /* 释放功能间MBOX通道 */

int hinic3_mbox_to_host(struct hinic3_hwdev *hwdev, u16 dest_host_ppf_id,
			enum hinic3_mod_type mod, u8 cmd, void *buf_in,
			u16 in_size, void *buf_out, u16 *out_size, u32 timeout, u16 channel); /* 发送到对端主机PPF */

int hinic3_mbox_to_func_no_ack(struct hinic3_hwdev *hwdev, u16 func_idx,
			       u8 mod, u16 cmd, void *buf_in, u16 in_size,
			       u16 channel); /* 发送到功能且无需ACK */

int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
			     void *buf_in, u16 in_size, void *buf_out,
			     u16 *out_size, u32 timeout, u16 channel); /* 发送到管理CPU并等待响应 */

void hinic3_response_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
				  void *buf_in, u16 in_size, u16 msg_id); /* 向管理CPU发送响应 */

int hinic3_send_mbox_to_mgmt_no_ack(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
				    void *buf_in, u16 in_size, u16 channel);
int hinic3_mbox_to_func(struct hinic3_mbox *func_to_func, u8 mod, u16 cmd,
			u16 dst_func, void *buf_in, u16 in_size,
			void *buf_out, u16 *out_size, u32 timeout, u16 channel); /* 功能间MBOX（PF<->VF） */

int hinic3_mbox_init_host_msg_channel(struct hinic3_hwdev *hwdev); /* 初始化主机间消息通道 */

void hinic3_mbox_enable_channel_lock(struct hinic3_hwdev *hwdev, bool enable); /* 打开/关闭通道锁 */

#endif

